#ifndef RTC5AGENT_H
#define RTC5AGENT_H

#include <string>
#include <list>
#include <QMap>
#include <QString>
#include "../app/system/systemconfig.h"

using namespace std;

#define RTC5AGENT HIM::RTC5Agent::getInstance()
namespace HIM {

enum RTC5E
{
    //No board found(this error can only occur by init_rtc5_dll).
    RTC5_NO_CARD,
    //Access denied(this error can occur by init_rtc5_dll,
    //select_rtc, acquire_rtc or any multiboard command).
    RTC5_ACCESS_DENIED,
    //Command not forwarded  (this error implies an
    //internal, PCI or driver error, for example, caused by a
    //hardware defect or an incorrect connection).
    RTC5_SEND_ERROR,
    //No response from board(it is likely that no program
    //has been loaded onto the RTC5; this error can
    //especially occur in connection with control
    //commands that expect a response, for example, get_head_para).
    RTC5_TIMEOUT,
    //Invalid parameter(this error can occur through
    //all commands for which invalid parameters are not
    //automatically corrected to valid values, for example,
    //parameters with limited choices such as get_head_para; if this error
    //occurs for a list command, it is replaced with list_nop; if this error
    //occurs for a control command, it is not executed).
    RTC5_PARAM_ERROR,
    //List processing is (not) active (for example, for execute_list, if a list is
    //currently being processed for example, for stop_execution, if no list is
    //currently being processed for example, for restart_list, if pause_list has
    //not been previously called).
    RTC5_BUSY,
    //List command rejected, illegal input pointer
    //(for example, for any list command directly after
    //load_char + list_return: the list command is then not loaded).
    RTC5_REJECTED,
    // List command has been converted to a list_nop (for example,
    //set_end_of_list in a protected subroutine).
    RTC5_IGNORED,
    //Version error: RTC5 DLL version, RTC5RBF.rbf version
    //and RTC5OUT.out version are  not compatible with each  other.
    //See also load_program_file.
    RTC5_VERSION_MISMATCH,
    //Verify error: The download verification (see page 113)
    //has detected an incorrect download.
    RTC5_VERIFY_ERROR,
    /*
     * DSP version error: DSP version too old (this error only occurs with older RTC5 Boards,
     * see get_rtc_version Bit #16…Bit #23 – and only through a few commands such as mark_ellipse_abs;
     * the corresponding command description’s “Version info” section contains related comments;
     * Commands that generate the error are neither executed nor replaced by list_nop).
     */
    RTC5_TYPE_REJECTED,
    //A RTC5 DLL-internal Windows memory request failed.
    RTC5_OUT_OF_MEMORY,
    //EEPROM read or write error(can occur during initialization or auto_cal).
    RTC5_EEPROM_ERROR,
    //Error reading PCI configuration register (can only occur during init_rtc5_dll).
    RTC5_CONFIG_ERROR = 16
};

typedef enum
{
    LOAD1,
    LOAD2,
    READY1,
    READY2,
    BUSY1,
    BUSY2,
    USED1,
    USED2,
}ListStatus;

class RTC5Agent
{
public:
    static RTC5Agent& getInstance(){
        static RTC5Agent rtc5Agent;
        return rtc5Agent;
    }

    bool Start();
    bool init();
    void Free();
    bool LoadCt5(string ct5path, int tableIndex);
    bool CheckError();
    void getErrStr(UINT errCode , QString& errStr);

    bool getRtcIsInit(){
        return initSuccess;
    }

    void loadAllLaserConfig();
    void ApplyLaserConfig();

    bool getLaserError();

    bool scanSlicelayer();

    void MarkStart();
    void MakePause();
    void MakeResume();
    unsigned int MarkEnd();
    bool MarkStop();
    bool IsMarking();

    bool ctlEnableLaser(bool en);
    void ctlSetHomePosition(double vX, double vY);
    void ctlSetLaserPinOut(unsigned int pins);
    bool ctrlSetJumpSpeed(double jump);
    void ctlSetScaleAngle(double , double , double );
    void ctlSetOffsetPosition(double , double , double );
    void ctlSetFrequency(INT32 , UINT32);

    void listSetMarkSpeed(double mark);
    void listSetLaserPower(double value);
    void listSetDelayMode(INT32 jumpDelay);
    void listSetDelayTime(INT32,INT32,INT32,INT32,INT32);
    void listSetSkyWritring(INT32,INT32,INT32,INT32,INT32);

    void testLensPara(QMap<QString,double>);
    void testCalibrationPara(QMap<QString,double>);
    void testGoto(QMap<QString,double>);
    void testTimedlight(QMap<QString,double>);
    void testLines(QMap<QString,double>);
    void testCircle(QMap<QString,double>);
    void testRectangle(QMap<QString,double>);
    void testSlicelayer(QMap<QString,double>);

    void gotoXY(UINT,double x, double y);
    void jumpAbs(UINT,double x, double y);
    void markAbs(UINT,double x, double y);

    void setSkyWritingOn(bool value){
        skyWritingOn = value;
    }

private :
    RTC5Agent();
    ~RTC5Agent();
    RTC5Agent(const RTC5Agent&)=delete;
    RTC5Agent& operator = (const RTC5Agent&)=delete;

    unsigned int listMark{1};

    bool isConnect_RTCA;
    bool isConnect_RTCB;

    bool initSuccess{false};   

    bool skyWritingOn{true};

    const UINT32 LIST1_2_CONUT = 500000;

    //激光位置 bits / mm
    double kFactor      =   400.0;
    double kFactorX     =   400.0;
    double kFactorY     =   400.0;

    string laserCalibrationFilePath = "../data/rtc5/Cor_1to1.ct5";

    //激光参数
    INT32 laserPowerMax {0};

    INT32 laserTestPower {0};
    INT32 laserJumpSpeed {0};
    INT32 laserMarkSpeed {0};
    INT32 laserFrequency  {0};
    UINT32 laserPulseWidth {0};

    INT32 laserOnDelay {0};
    INT32 laserOffDelay {0};
    INT32 laserJumpDelay  {0};
    INT32 laserMarkDelay  {0};
    INT32 laserPolyDelay  {0};

    INT32 laserSkyWritingTimelag {0};
    INT32 laserSkyWritingNprev {0};
    INT32 laserSkyWritingOnShift  {0};
    INT32 laserSkyWritingNpost  {0};
    INT32 laserSkyWritingAngle  {0};

    double laserPowerByLen2d0 {0};
    double laserPowerByLen1d0 {0};
    double laserPowerByLen0d5 {0};
    double laserPowerByLen0d2 {0};

    //镜头参数
    double laserXmove {0};
    double laserYmove {0};
    double laserXScale {1};
    double laserYScale {1};
    double laserXYrotate {0};

    UINT laserAIndex{1};

    int sizeXY{0};

    int laserCurrentPower{0};

};
}

#endif // RTC5AGENT_H
